home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / pmove.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-08-13  |  28.1 KB  |  1,361 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20.  
  21. #include "qcommon.h"
  22.  
  23.  
  24.  
  25. #define    STEPSIZE    18
  26.  
  27. // all of the locals will be zeroed before each
  28. // pmove, just to make damn sure we don't have
  29. // any differences when running on client or server
  30.  
  31. typedef struct
  32. {
  33.     vec3_t        origin;            // full float precision
  34.     vec3_t        velocity;        // full float precision
  35.  
  36.     vec3_t        forward, right, up;
  37.     float        frametime;
  38.  
  39.  
  40.     csurface_t    *groundsurface;
  41.     cplane_t    groundplane;
  42.     int            groundcontents;
  43.  
  44.     vec3_t        previous_origin;
  45.     qboolean    ladder;
  46. } pml_t;
  47.  
  48. pmove_t        *pm;
  49. pml_t        pml;
  50.  
  51.  
  52. // movement parameters
  53. float    pm_stopspeed = 100;
  54. float    pm_maxspeed = 300;
  55. float    pm_duckspeed = 100;
  56. float    pm_accelerate = 10;
  57. float    pm_airaccelerate = 0;
  58. float    pm_wateraccelerate = 10;
  59. float    pm_friction = 6;
  60. float    pm_waterfriction = 1;
  61. float    pm_waterspeed = 400;
  62.  
  63. /*
  64.  
  65.   walking up a step should kill some velocity
  66.  
  67. */
  68.  
  69.  
  70. /*
  71. ==================
  72. PM_ClipVelocity
  73.  
  74. Slide off of the impacting object
  75. returns the blocked flags (1 = floor, 2 = step / wall)
  76. ==================
  77. */
  78. #define    STOP_EPSILON    0.1
  79.  
  80. void PM_ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
  81. {
  82.     float    backoff;
  83.     float    change;
  84.     int        i;
  85.     
  86.     backoff = DotProduct (in, normal) * overbounce;
  87.  
  88.     for (i=0 ; i<3 ; i++)
  89.     {
  90.         change = normal[i]*backoff;
  91.         out[i] = in[i] - change;
  92.         if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
  93.             out[i] = 0;
  94.     }
  95. }
  96.  
  97.  
  98.  
  99.  
  100. /*
  101. ==================
  102. PM_StepSlideMove
  103.  
  104. Each intersection will try to step over the obstruction instead of
  105. sliding along it.
  106.  
  107. Returns a new origin, velocity, and contact entity
  108. Does not modify any world state?
  109. ==================
  110. */
  111. #define    MIN_STEP_NORMAL    0.7        // can't step up onto very steep slopes
  112. #define    MAX_CLIP_PLANES    5
  113. void PM_StepSlideMove_ (void)
  114. {
  115.     int            bumpcount, numbumps;
  116.     vec3_t        dir;
  117.     float        d;
  118.     int            numplanes;
  119.     vec3_t        planes[MAX_CLIP_PLANES];
  120.     vec3_t        primal_velocity;
  121.     int            i, j;
  122.     trace_t    trace;
  123.     vec3_t        end;
  124.     float        time_left;
  125.     
  126.     numbumps = 4;
  127.     
  128.     VectorCopy (pml.velocity, primal_velocity);
  129.     numplanes = 0;
  130.     
  131.     time_left = pml.frametime;
  132.  
  133.     for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
  134.     {
  135.         for (i=0 ; i<3 ; i++)
  136.             end[i] = pml.origin[i] + time_left * pml.velocity[i];
  137.  
  138.         trace = pm->trace (pml.origin, pm->mins, pm->maxs, end);
  139.  
  140.         if (trace.allsolid)
  141.         {    // entity is trapped in another solid
  142.             pml.velocity[2] = 0;    // don't build up falling damage
  143.             return;
  144.         }
  145.  
  146.         if (trace.fraction > 0)
  147.         {    // actually covered some distance
  148.             VectorCopy (trace.endpos, pml.origin);
  149.             numplanes = 0;
  150.         }
  151.  
  152.         if (trace.fraction == 1)
  153.              break;        // moved the entire distance
  154.  
  155.         // save entity for contact
  156.         if (pm->numtouch < MAXTOUCH && trace.ent)
  157.         {
  158.             pm->touchents[pm->numtouch] = trace.ent;
  159.             pm->numtouch++;
  160.         }
  161.         
  162.         time_left -= time_left * trace.fraction;
  163.  
  164.         // slide along this plane
  165.         if (numplanes >= MAX_CLIP_PLANES)
  166.         {    // this shouldn't really happen
  167.             VectorCopy (vec3_origin, pml.velocity);
  168.             break;
  169.         }
  170.  
  171.         VectorCopy (trace.plane.normal, planes[numplanes]);
  172.         numplanes++;
  173.  
  174. #if 0
  175.     float        rub;
  176.  
  177.         //
  178.         // modify velocity so it parallels all of the clip planes
  179.         //
  180.         if (numplanes == 1)
  181.         {    // go along this plane
  182.             VectorCopy (pml.velocity, dir);
  183.             VectorNormalize (dir);
  184.             rub = 1.0 + 0.5 * DotProduct (dir, planes[0]);
  185.  
  186.             // slide along the plane
  187.             PM_ClipVelocity (pml.velocity, planes[0], pml.velocity, 1.01);
  188.             // rub some extra speed off on xy axis
  189.             // not on Z, or you can scrub down walls
  190.             pml.velocity[0] *= rub;
  191.             pml.velocity[1] *= rub;
  192.             pml.velocity[2] *= rub;
  193.         }
  194.         else if (numplanes == 2)
  195.         {    // go along the crease
  196.             VectorCopy (pml.velocity, dir);
  197.             VectorNormalize (dir);
  198.             rub = 1.0 + 0.5 * DotProduct (dir, planes[0]);
  199.  
  200.             // slide along the plane
  201.             CrossProduct (planes[0], planes[1], dir);
  202.             d = DotProduct (dir, pml.velocity);
  203.             VectorScale (dir, d, pml.velocity);
  204.  
  205.             // rub some extra speed off
  206.             VectorScale (pml.velocity, rub, pml.velocity);
  207.         }
  208.         else
  209.         {
  210. //            Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
  211.             VectorCopy (vec3_origin, pml.velocity);
  212.             break;
  213.         }
  214.  
  215. #else
  216. //
  217. // modify original_velocity so it parallels all of the clip planes
  218. //
  219.         for (i=0 ; i<numplanes ; i++)
  220.         {
  221.             PM_ClipVelocity (pml.velocity, planes[i], pml.velocity, 1.01);
  222.             for (j=0 ; j<numplanes ; j++)
  223.                 if (j != i)
  224.                 {
  225.                     if (DotProduct (pml.velocity, planes[j]) < 0)
  226.                         break;    // not ok
  227.                 }
  228.             if (j == numplanes)
  229.                 break;
  230.         }
  231.         
  232.         if (i != numplanes)
  233.         {    // go along this plane
  234.         }
  235.         else
  236.         {    // go along the crease
  237.             if (numplanes != 2)
  238.             {
  239. //                Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
  240.                 VectorCopy (vec3_origin, pml.velocity);
  241.                 break;
  242.             }
  243.             CrossProduct (planes[0], planes[1], dir);
  244.             d = DotProduct (dir, pml.velocity);
  245.             VectorScale (dir, d, pml.velocity);
  246.         }
  247. #endif
  248.         //
  249.         // if velocity is against the original velocity, stop dead
  250.         // to avoid tiny occilations in sloping corners
  251.         //
  252.         if (DotProduct (pml.velocity, primal_velocity) <= 0)
  253.         {
  254.             VectorCopy (vec3_origin, pml.velocity);
  255.             break;
  256.         }
  257.     }
  258.  
  259.     if (pm->s.pm_time)
  260.     {
  261.         VectorCopy (primal_velocity, pml.velocity);
  262.     }
  263. }
  264.  
  265. /*
  266. ==================
  267. PM_StepSlideMove
  268.  
  269. ==================
  270. */
  271. void PM_StepSlideMove (void)
  272. {
  273.     vec3_t        start_o, start_v;
  274.     vec3_t        down_o, down_v;
  275.     trace_t        trace;
  276.     float        down_dist, up_dist;
  277. //    vec3_t        delta;
  278.     vec3_t        up, down;
  279.  
  280.     VectorCopy (pml.origin, start_o);
  281.     VectorCopy (pml.velocity, start_v);
  282.  
  283.     PM_StepSlideMove_ ();
  284.  
  285.     VectorCopy (pml.origin, down_o);
  286.     VectorCopy (pml.velocity, down_v);
  287.  
  288.     VectorCopy (start_o, up);
  289.     up[2] += STEPSIZE;
  290.  
  291.     trace = pm->trace (up, pm->mins, pm->maxs, up);
  292.     if (trace.allsolid)
  293.         return;        // can't step up
  294.  
  295.     // try sliding above
  296.     VectorCopy (up, pml.origin);
  297.     VectorCopy (start_v, pml.velocity);
  298.  
  299.     PM_StepSlideMove_ ();
  300.  
  301.     // push down the final amount
  302.     VectorCopy (pml.origin, down);
  303.     down[2] -= STEPSIZE;
  304.     trace = pm->trace (pml.origin, pm->mins, pm->maxs, down);
  305.     if (!trace.allsolid)
  306.     {
  307.         VectorCopy (trace.endpos, pml.origin);
  308.     }
  309.  
  310. #if 0
  311.     VectorSubtract (pml.origin, up, delta);
  312.     up_dist = DotProduct (delta, start_v);
  313.  
  314.     VectorSubtract (down_o, start_o, delta);
  315.     down_dist = DotProduct (delta, start_v);
  316. #else
  317.     VectorCopy(pml.origin, up);
  318.  
  319.     // decide which one went farther
  320.     down_dist = (down_o[0] - start_o[0])*(down_o[0] - start_o[0])
  321.         + (down_o[1] - start_o[1])*(down_o[1] - start_o[1]);
  322.     up_dist = (up[0] - start_o[0])*(up[0] - start_o[0])
  323.         + (up[1] - start_o[1])*(up[1] - start_o[1]);
  324. #endif
  325.  
  326.     if (down_dist > up_dist || trace.plane.normal[2] < MIN_STEP_NORMAL)
  327.     {
  328.         VectorCopy (down_o, pml.origin);
  329.         VectorCopy (down_v, pml.velocity);
  330.         return;
  331.     }
  332.     //!! Special case
  333.     // if we were walking along a plane, then we need to copy the Z over
  334.     pml.velocity[2] = down_v[2];
  335. }
  336.  
  337.  
  338. /*
  339. ==================
  340. PM_Friction
  341.  
  342. Handles both ground friction and water friction
  343. ==================
  344. */
  345. void PM_Friction (void)
  346. {
  347.     float    *vel;
  348.     float    speed, newspeed, control;
  349.     float    friction;
  350.     float    drop;
  351.     
  352.     vel = pml.velocity;
  353.     
  354.     speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1] + vel[2]*vel[2]);
  355.     if (speed < 1)
  356.     {
  357.         vel[0] = 0;
  358.         vel[1] = 0;
  359.         return;
  360.     }
  361.  
  362.     drop = 0;
  363.  
  364. // apply ground friction
  365.     if ((pm->groundentity && pml.groundsurface && !(pml.groundsurface->flags & SURF_SLICK) ) || (pml.ladder) )
  366.     {
  367.         friction = pm_friction;
  368.         control = speed < pm_stopspeed ? pm_stopspeed : speed;
  369.         drop += control*friction*pml.frametime;
  370.     }
  371.  
  372. // apply water friction
  373.     if (pm->waterlevel && !pml.ladder)
  374.         drop += speed*pm_waterfriction*pm->waterlevel*pml.frametime;
  375.  
  376. // scale the velocity
  377.     newspeed = speed - drop;
  378.     if (newspeed < 0)
  379.     {
  380.         newspeed = 0;
  381.     }
  382.     newspeed /= speed;
  383.  
  384.     vel[0] = vel[0] * newspeed;
  385.     vel[1] = vel[1] * newspeed;
  386.     vel[2] = vel[2] * newspeed;
  387. }
  388.  
  389.  
  390. /*
  391. ==============
  392. PM_Accelerate
  393.  
  394. Handles user intended acceleration
  395. ==============
  396. */
  397. void PM_Accelerate (vec3_t wishdir, float wishspeed, float accel)
  398. {
  399.     int            i;
  400.     float        addspeed, accelspeed, currentspeed;
  401.  
  402.     currentspeed = DotProduct (pml.velocity, wishdir);
  403.     addspeed = wishspeed - currentspeed;
  404.     if (addspeed <= 0)
  405.         return;
  406.     accelspeed = accel*pml.frametime*wishspeed;
  407.     if (accelspeed > addspeed)
  408.         accelspeed = addspeed;
  409.     
  410.     for (i=0 ; i<3 ; i++)
  411.         pml.velocity[i] += accelspeed*wishdir[i];    
  412. }
  413.  
  414. void PM_AirAccelerate (vec3_t wishdir, float wishspeed, float accel)
  415. {
  416.     int            i;
  417.     float        addspeed, accelspeed, currentspeed, wishspd = wishspeed;
  418.         
  419.     if (wishspd > 30)
  420.         wishspd = 30;
  421.     currentspeed = DotProduct (pml.velocity, wishdir);
  422.     addspeed = wishspd - currentspeed;
  423.     if (addspeed <= 0)
  424.         return;
  425.     accelspeed = accel * wishspeed * pml.frametime;
  426.     if (accelspeed > addspeed)
  427.         accelspeed = addspeed;
  428.     
  429.     for (i=0 ; i<3 ; i++)
  430.         pml.velocity[i] += accelspeed*wishdir[i];    
  431. }
  432.  
  433. /*
  434. =============
  435. PM_AddCurrents
  436. =============
  437. */
  438. void PM_AddCurrents (vec3_t    wishvel)
  439. {
  440.     vec3_t    v;
  441.     float    s;
  442.  
  443.     //
  444.     // account for ladders
  445.     //
  446.  
  447.     if (pml.ladder && fabs(pml.velocity[2]) <= 200)
  448.     {
  449.         if ((pm->viewangles[PITCH] <= -15) && (pm->cmd.forwardmove > 0))
  450.             wishvel[2] = 200;
  451.         else if ((pm->viewangles[PITCH] >= 15) && (pm->cmd.forwardmove > 0))
  452.             wishvel[2] = -200;
  453.         else if (pm->cmd.upmove > 0)
  454.             wishvel[2] = 200;
  455.         else if (pm->cmd.upmove < 0)
  456.             wishvel[2] = -200;
  457.         else
  458.             wishvel[2] = 0;
  459.  
  460.         // limit horizontal speed when on a ladder
  461.         if (wishvel[0] < -25)
  462.             wishvel[0] = -25;
  463.         else if (wishvel[0] > 25)
  464.             wishvel[0] = 25;
  465.  
  466.         if (wishvel[1] < -25)
  467.             wishvel[1] = -25;
  468.         else if (wishvel[1] > 25)
  469.             wishvel[1] = 25;
  470.     }
  471.  
  472.  
  473.     //
  474.     // add water currents
  475.     //
  476.  
  477.     if (pm->watertype & MASK_CURRENT)
  478.     {
  479.         VectorClear (v);
  480.  
  481.         if (pm->watertype & CONTENTS_CURRENT_0)
  482.             v[0] += 1;
  483.         if (pm->watertype & CONTENTS_CURRENT_90)
  484.             v[1] += 1;
  485.         if (pm->watertype & CONTENTS_CURRENT_180)
  486.             v[0] -= 1;
  487.         if (pm->watertype & CONTENTS_CURRENT_270)
  488.             v[1] -= 1;
  489.         if (pm->watertype & CONTENTS_CURRENT_UP)
  490.             v[2] += 1;
  491.         if (pm->watertype & CONTENTS_CURRENT_DOWN)
  492.             v[2] -= 1;
  493.  
  494.         s = pm_waterspeed;
  495.         if ((pm->waterlevel == 1) && (pm->groundentity))
  496.             s /= 2;
  497.  
  498.         VectorMA (wishvel, s, v, wishvel);
  499.     }
  500.  
  501.     //
  502.     // add conveyor belt velocities
  503.     //
  504.  
  505.     if (pm->groundentity)
  506.     {
  507.         VectorClear (v);
  508.  
  509.         if (pml.groundcontents & CONTENTS_CURRENT_0)
  510.             v[0] += 1;
  511.         if (pml.groundcontents & CONTENTS_CURRENT_90)
  512.             v[1] += 1;
  513.         if (pml.groundcontents & CONTENTS_CURRENT_180)
  514.             v[0] -= 1;
  515.         if (pml.groundcontents & CONTENTS_CURRENT_270)
  516.             v[1] -= 1;
  517.         if (pml.groundcontents & CONTENTS_CURRENT_UP)
  518.             v[2] += 1;
  519.         if (pml.groundcontents & CONTENTS_CURRENT_DOWN)
  520.             v[2] -= 1;
  521.  
  522.         VectorMA (wishvel, 100 /* pm->groundentity->speed */, v, wishvel);
  523.     }
  524. }
  525.  
  526.  
  527. /*
  528. ===================
  529. PM_WaterMove
  530.  
  531. ===================
  532. */
  533. void PM_WaterMove (void)
  534. {
  535.     int        i;
  536.     vec3_t    wishvel;
  537.     float    wishspeed;
  538.     vec3_t    wishdir;
  539.  
  540. //
  541. // user intentions
  542. //
  543.     for (i=0 ; i<3 ; i++)
  544.         wishvel[i] = pml.forward[i]*pm->cmd.forwardmove + pml.right[i]*pm->cmd.sidemove;
  545.  
  546.     if (!pm->cmd.forwardmove && !pm->cmd.sidemove && !pm->cmd.upmove)
  547.         wishvel[2] -= 60;        // drift towards bottom
  548.     else
  549.         wishvel[2] += pm->cmd.upmove;
  550.  
  551.     PM_AddCurrents (wishvel);
  552.  
  553.     VectorCopy (wishvel, wishdir);
  554.     wishspeed = VectorNormalize(wishdir);
  555.  
  556.     if (wishspeed > pm_maxspeed)
  557.     {
  558.         VectorScale (wishvel, pm_maxspeed/wishspeed, wishvel);
  559.         wishspeed = pm_maxspeed;
  560.     }
  561.     wishspeed *= 0.5;
  562.  
  563.     PM_Accelerate (wishdir, wishspeed, pm_wateraccelerate);
  564.  
  565.     PM_StepSlideMove ();
  566. }
  567.  
  568.  
  569. /*
  570. ===================
  571. PM_AirMove
  572.  
  573. ===================
  574. */
  575. void PM_AirMove (void)
  576. {
  577.     int            i;
  578.     vec3_t        wishvel;
  579.     float        fmove, smove;
  580.     vec3_t        wishdir;
  581.     float        wishspeed;
  582.     float        maxspeed;
  583.  
  584.     fmove = pm->cmd.forwardmove;
  585.     smove = pm->cmd.sidemove;
  586.     
  587. //!!!!! pitch should be 1/3 so this isn't needed??!
  588. #if 0
  589.     pml.forward[2] = 0;
  590.     pml.right[2] = 0;
  591.     VectorNormalize (pml.forward);
  592.     VectorNormalize (pml.right);
  593. #endif
  594.  
  595.     for (i=0 ; i<2 ; i++)
  596.         wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
  597.     wishvel[2] = 0;
  598.  
  599.     PM_AddCurrents (wishvel);
  600.  
  601.     VectorCopy (wishvel, wishdir);
  602.     wishspeed = VectorNormalize(wishdir);
  603.  
  604. //
  605. // clamp to server defined max speed
  606. //
  607.     maxspeed = (pm->s.pm_flags & PMF_DUCKED) ? pm_duckspeed : pm_maxspeed;
  608.  
  609.     if (wishspeed > maxspeed)
  610.     {
  611.         VectorScale (wishvel, maxspeed/wishspeed, wishvel);
  612.         wishspeed = maxspeed;
  613.     }
  614.     
  615.     if ( pml.ladder )
  616.     {
  617.         PM_Accelerate (wishdir, wishspeed, pm_accelerate);
  618.         if (!wishvel[2])
  619.         {
  620.             if (pml.velocity[2] > 0)
  621.             {
  622.                 pml.velocity[2] -= pm->s.gravity * pml.frametime;
  623.                 if (pml.velocity[2] < 0)
  624.                     pml.velocity[2]  = 0;
  625.             }
  626.             else
  627.             {
  628.                 pml.velocity[2] += pm->s.gravity * pml.frametime;
  629.                 if (pml.velocity[2] > 0)
  630.                     pml.velocity[2]  = 0;
  631.             }
  632.         }
  633.         PM_StepSlideMove ();
  634.     }
  635.     else if ( pm->groundentity )
  636.     {    // walking on ground
  637.         pml.velocity[2] = 0; //!!! this is before the accel
  638.         PM_Accelerate (wishdir, wishspeed, pm_accelerate);
  639.  
  640. // PGM    -- fix for negative trigger_gravity fields
  641. //        pml.velocity[2] = 0;
  642.         if(pm->s.gravity > 0)
  643.             pml.velocity[2] = 0;
  644.         else
  645.             pml.velocity[2] -= pm->s.gravity * pml.frametime;
  646. // PGM
  647.  
  648.         if (!pml.velocity[0] && !pml.velocity[1])
  649.             return;
  650.         PM_StepSlideMove ();
  651.     }
  652.     else
  653.     {    // not on ground, so little effect on velocity
  654.         if (pm_airaccelerate)
  655.             PM_AirAccelerate (wishdir, wishspeed, pm_accelerate);
  656.         else
  657.             PM_Accelerate (wishdir, wishspeed, 1);
  658.         // add gravity
  659.         pml.velocity[2] -= pm->s.gravity * pml.frametime;
  660.         PM_StepSlideMove ();
  661.     }
  662. }
  663.  
  664.  
  665.  
  666. /*
  667. =============
  668. PM_CatagorizePosition
  669. =============
  670. */
  671. void PM_CatagorizePosition (void)
  672. {
  673.     vec3_t        point;
  674.     int            cont;
  675.     trace_t        trace;
  676.     int            sample1;
  677.     int            sample2;
  678.  
  679. // if the player hull point one unit down is solid, the player
  680. // is on ground
  681.  
  682. // see if standing on something solid    
  683.     point[0] = pml.origin[0];
  684.     point[1] = pml.origin[1];
  685.     point[2] = pml.origin[2] - 0.25;
  686.     if (pml.velocity[2] > 180) //!!ZOID changed from 100 to 180 (ramp accel)
  687.     {
  688.         pm->s.pm_flags &= ~PMF_ON_GROUND;
  689.         pm->groundentity = NULL;
  690.     }
  691.     else
  692.     {
  693.         trace = pm->trace (pml.origin, pm->mins, pm->maxs, point);
  694.         pml.groundplane = trace.plane;
  695.         pml.groundsurface = trace.surface;
  696.         pml.groundcontents = trace.contents;
  697.  
  698.         if (!trace.ent || (trace.plane.normal[2] < 0.7 && !trace.startsolid) )
  699.         {
  700.             pm->groundentity = NULL;
  701.             pm->s.pm_flags &= ~PMF_ON_GROUND;
  702.         }
  703.         else
  704.         {
  705.             pm->groundentity = trace.ent;
  706.  
  707.             // hitting solid ground will end a waterjump
  708.             if (pm->s.pm_flags & PMF_TIME_WATERJUMP)
  709.             {
  710.                 pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT);
  711.                 pm->s.pm_time = 0;
  712.             }
  713.  
  714.             if (! (pm->s.pm_flags & PMF_ON_GROUND) )
  715.             {    // just hit the ground
  716.                 pm->s.pm_flags |= PMF_ON_GROUND;
  717.                 // don't do landing time if we were just going down a slope
  718.                 if (pml.velocity[2] < -200)
  719.                 {
  720.                     pm->s.pm_flags |= PMF_TIME_LAND;
  721.                     // don't allow another jump for a little while
  722.                     if (pml.velocity[2] < -400)
  723.                         pm->s.pm_time = 25;    
  724.                     else
  725.                         pm->s.pm_time = 18;
  726.                 }
  727.             }
  728.         }
  729.  
  730. #if 0
  731.         if (trace.fraction < 1.0 && trace.ent && pml.velocity[2] < 0)
  732.             pml.velocity[2] = 0;
  733. #endif
  734.  
  735.         if (pm->numtouch < MAXTOUCH && trace.ent)
  736.         {
  737.             pm->touchents[pm->numtouch] = trace.ent;
  738.             pm->numtouch++;
  739.         }
  740.     }
  741.  
  742. //
  743. // get waterlevel, accounting for ducking
  744. //
  745.     pm->waterlevel = 0;
  746.     pm->watertype = 0;
  747.  
  748.     sample2 = pm->viewheight - pm->mins[2];
  749.     sample1 = sample2 / 2;
  750.  
  751.     point[2] = pml.origin[2] + pm->mins[2] + 1;    
  752.     cont = pm->pointcontents (point);
  753.  
  754.     if (cont & MASK_WATER)
  755.     {
  756.         pm->watertype = cont;
  757.         pm->waterlevel = 1;
  758.         point[2] = pml.origin[2] + pm->mins[2] + sample1;
  759.         cont = pm->pointcontents (point);
  760.         if (cont & MASK_WATER)
  761.         {
  762.             pm->waterlevel = 2;
  763.             point[2] = pml.origin[2] + pm->mins[2] + sample2;
  764.             cont = pm->pointcontents (point);
  765.             if (cont & MASK_WATER)
  766.                 pm->waterlevel = 3;
  767.         }
  768.     }
  769.  
  770. }
  771.  
  772.  
  773. /*
  774. =============
  775. PM_CheckJump
  776. =============
  777. */
  778. void PM_CheckJump (void)
  779. {
  780.     if (pm->s.pm_flags & PMF_TIME_LAND)
  781.     {    // hasn't been long enough since landing to jump again
  782.         return;
  783.     }
  784.  
  785.     if (pm->cmd.upmove < 10)
  786.     {    // not holding jump
  787.         pm->s.pm_flags &= ~PMF_JUMP_HELD;
  788.         return;
  789.     }
  790.  
  791.     // must wait for jump to be released
  792.     if (pm->s.pm_flags & PMF_JUMP_HELD)
  793.         return;
  794.  
  795.     if (pm->s.pm_type == PM_DEAD)
  796.         return;
  797.  
  798.     if (pm->waterlevel >= 2)
  799.     {    // swimming, not jumping
  800.         pm->groundentity = NULL;
  801.  
  802.         if (pml.velocity[2] <= -300)
  803.             return;
  804.  
  805.         if (pm->watertype == CONTENTS_WATER)
  806.             pml.velocity[2] = 100;
  807.         else if (pm->watertype == CONTENTS_SLIME)
  808.             pml.velocity[2] = 80;
  809.         else
  810.             pml.velocity[2] = 50;
  811.         return;
  812.     }
  813.  
  814.     if (pm->groundentity == NULL)
  815.         return;        // in air, so no effect
  816.  
  817.     pm->s.pm_flags |= PMF_JUMP_HELD;
  818.  
  819.     pm->groundentity = NULL;
  820.     pml.velocity[2] += 270;
  821.     if (pml.velocity[2] < 270)
  822.         pml.velocity[2] = 270;
  823. }
  824.  
  825.  
  826. /*
  827. =============
  828. PM_CheckSpecialMovement
  829. =============
  830. */
  831. void PM_CheckSpecialMovement (void)
  832. {
  833.     vec3_t    spot;
  834.     int        cont;
  835.     vec3_t    flatforward;
  836.     trace_t    trace;
  837.  
  838.     if (pm->s.pm_time)
  839.         return;
  840.  
  841.     pml.ladder = false;
  842.  
  843.     // check for ladder
  844.     flatforward[0] = pml.forward[0];
  845.     flatforward[1] = pml.forward[1];
  846.     flatforward[2] = 0;
  847.     VectorNormalize (flatforward);
  848.  
  849.     VectorMA (pml.origin, 1, flatforward, spot);
  850.     trace = pm->trace (pml.origin, pm->mins, pm->maxs, spot);
  851.     if ((trace.fraction < 1) && (trace.contents & CONTENTS_LADDER))
  852.         pml.ladder = true;
  853.  
  854.     // check for water jump
  855.     if (pm->waterlevel != 2)
  856.         return;
  857.  
  858.     VectorMA (pml.origin, 30, flatforward, spot);
  859.     spot[2] += 4;
  860.     cont = pm->pointcontents (spot);
  861.     if (!(cont & CONTENTS_SOLID))
  862.         return;
  863.  
  864.     spot[2] += 16;
  865.     cont = pm->pointcontents (spot);
  866.     if (cont)
  867.         return;
  868.     // jump out of water
  869.     VectorScale (flatforward, 50, pml.velocity);
  870.     pml.velocity[2] = 350;
  871.  
  872.     pm->s.pm_flags |= PMF_TIME_WATERJUMP;
  873.     pm->s.pm_time = 255;
  874. }
  875.  
  876.  
  877. /*
  878. ===============
  879. PM_FlyMove
  880. ===============
  881. */
  882. void PM_FlyMove (qboolean doclip)
  883. {
  884.     float    speed, drop, friction, control, newspeed;
  885.     float    currentspeed, addspeed, accelspeed;
  886.     int            i;
  887.     vec3_t        wishvel;
  888.     float        fmove, smove;
  889.     vec3_t        wishdir;
  890.     float        wishspeed;
  891.     vec3_t        end;
  892.     trace_t    trace;
  893.  
  894.     pm->viewheight = 22;
  895.  
  896.     // friction
  897.  
  898.     speed = VectorLength (pml.velocity);
  899.     if (speed < 1)
  900.     {
  901.         VectorCopy (vec3_origin, pml.velocity);
  902.     }
  903.     else
  904.     {
  905.         drop = 0;
  906.  
  907.         friction = pm_friction*1.5;    // extra friction
  908.         control = speed < pm_stopspeed ? pm_stopspeed : speed;
  909.         drop += control*friction*pml.frametime;
  910.  
  911.         // scale the velocity
  912.         newspeed = speed - drop;
  913.         if (newspeed < 0)
  914.             newspeed = 0;
  915.         newspeed /= speed;
  916.  
  917.         VectorScale (pml.velocity, newspeed, pml.velocity);
  918.     }
  919.  
  920.     // accelerate
  921.     fmove = pm->cmd.forwardmove;
  922.     smove = pm->cmd.sidemove;
  923.     
  924.     VectorNormalize (pml.forward);
  925.     VectorNormalize (pml.right);
  926.  
  927.     for (i=0 ; i<3 ; i++)
  928.         wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
  929.     wishvel[2] += pm->cmd.upmove;
  930.  
  931.     VectorCopy (wishvel, wishdir);
  932.     wishspeed = VectorNormalize(wishdir);
  933.  
  934.     //
  935.     // clamp to server defined max speed
  936.     //
  937.     if (wishspeed > pm_maxspeed)
  938.     {
  939.         VectorScale (wishvel, pm_maxspeed/wishspeed, wishvel);
  940.         wishspeed = pm_maxspeed;
  941.     }
  942.  
  943.  
  944.     currentspeed = DotProduct(pml.velocity, wishdir);
  945.     addspeed = wishspeed - currentspeed;
  946.     if (addspeed <= 0)
  947.         return;
  948.     accelspeed = pm_accelerate*pml.frametime*wishspeed;
  949.     if (accelspeed > addspeed)
  950.         accelspeed = addspeed;
  951.     
  952.     for (i=0 ; i<3 ; i++)
  953.         pml.velocity[i] += accelspeed*wishdir[i];    
  954.  
  955.     if (doclip) {
  956.         for (i=0 ; i<3 ; i++)
  957.             end[i] = pml.origin[i] + pml.frametime * pml.velocity[i];
  958.  
  959.         trace = pm->trace (pml.origin, pm->mins, pm->maxs, end);
  960.  
  961.         VectorCopy (trace.endpos, pml.origin);
  962.     } else {
  963.         // move
  964.         VectorMA (pml.origin, pml.frametime, pml.velocity, pml.origin);
  965.     }
  966. }
  967.  
  968.  
  969. /*
  970. ==============
  971. PM_CheckDuck
  972.  
  973. Sets mins, maxs, and pm->viewheight
  974. ==============
  975. */
  976. void PM_CheckDuck (void)
  977. {
  978.     trace_t    trace;
  979.  
  980.     pm->mins[0] = -16;
  981.     pm->mins[1] = -16;
  982.  
  983.     pm->maxs[0] = 16;
  984.     pm->maxs[1] = 16;
  985.  
  986.     if (pm->s.pm_type == PM_GIB)
  987.     {
  988.         pm->mins[2] = 0;
  989.         pm->maxs[2] = 16;
  990.         pm->viewheight = 8;
  991.         return;
  992.     }
  993.  
  994.     pm->mins[2] = -24;
  995.  
  996.     if (pm->s.pm_type == PM_DEAD)
  997.     {
  998.         pm->s.pm_flags |= PMF_DUCKED;
  999.     }
  1000.     else if (pm->cmd.upmove < 0 && (pm->s.pm_flags & PMF_ON_GROUND) )
  1001.     {    // duck
  1002.         pm->s.pm_flags |= PMF_DUCKED;
  1003.     }
  1004.     else
  1005.     {    // stand up if possible
  1006.         if (pm->s.pm_flags & PMF_DUCKED)
  1007.         {
  1008.             // try to stand up
  1009.             pm->maxs[2] = 32;
  1010.             trace = pm->trace (pml.origin, pm->mins, pm->maxs, pml.origin);
  1011.             if (!trace.allsolid)
  1012.                 pm->s.pm_flags &= ~PMF_DUCKED;
  1013.         }
  1014.     }
  1015.  
  1016.     if (pm->s.pm_flags & PMF_DUCKED)
  1017.     {
  1018.         pm->maxs[2] = 4;
  1019.         pm->viewheight = -2;
  1020.     }
  1021.     else
  1022.     {
  1023.         pm->maxs[2] = 32;
  1024.         pm->viewheight = 22;
  1025.     }
  1026. }
  1027.  
  1028.  
  1029. /*
  1030. ==============
  1031. PM_DeadMove
  1032. ==============
  1033. */
  1034. void PM_DeadMove (void)
  1035. {
  1036.     float    forward;
  1037.  
  1038.     if (!pm->groundentity)
  1039.         return;
  1040.  
  1041.     // extra friction
  1042.  
  1043.     forward = VectorLength (pml.velocity);
  1044.     forward -= 20;
  1045.     if (forward <= 0)
  1046.     {
  1047.         VectorClear (pml.velocity);
  1048.     }
  1049.     else
  1050.     {
  1051.         VectorNormalize (pml.velocity);
  1052.         VectorScale (pml.velocity, forward, pml.velocity);
  1053.     }
  1054. }
  1055.  
  1056.  
  1057. qboolean    PM_GoodPosition (void)
  1058. {
  1059.     trace_t    trace;
  1060.     vec3_t    origin, end;
  1061.     int        i;
  1062.  
  1063.     if (pm->s.pm_type == PM_SPECTATOR)
  1064.         return true;
  1065.  
  1066.     for (i=0 ; i<3 ; i++)
  1067.         origin[i] = end[i] = pm->s.origin[i]*0.125;
  1068.     trace = pm->trace (origin, pm->mins, pm->maxs, end);
  1069.  
  1070.     return !trace.allsolid;
  1071. }
  1072.  
  1073. /*
  1074. ================
  1075. PM_SnapPosition
  1076.  
  1077. On exit, the origin will have a value that is pre-quantized to the 0.125
  1078. precision of the network channel and in a valid position.
  1079. ================
  1080. */
  1081. void PM_SnapPosition (void)
  1082. {
  1083.     int        sign[3];
  1084.     int        i, j, bits;
  1085.     short    base[3];
  1086.     // try all single bits first
  1087.     static int jitterbits[8] = {0,4,1,2,3,5,6,7};
  1088.  
  1089.     // snap velocity to eigths
  1090.     for (i=0 ; i<3 ; i++)
  1091.         pm->s.velocity[i] = (int)(pml.velocity[i]*8);
  1092.  
  1093.     for (i=0 ; i<3 ; i++)
  1094.     {
  1095.         if (pml.origin[i] >= 0)
  1096.             sign[i] = 1;
  1097.         else 
  1098.             sign[i] = -1;
  1099.         pm->s.origin[i] = (int)(pml.origin[i]*8);
  1100.         if (pm->s.origin[i]*0.125 == pml.origin[i])
  1101.             sign[i] = 0;
  1102.     }
  1103.     VectorCopy (pm->s.origin, base);
  1104.  
  1105.     // try all combinations
  1106.     for (j=0 ; j<8 ; j++)
  1107.     {
  1108.         bits = jitterbits[j];
  1109.         VectorCopy (base, pm->s.origin);
  1110.         for (i=0 ; i<3 ; i++)
  1111.             if (bits & (1<<i) )
  1112.                 pm->s.origin[i] += sign[i];
  1113.  
  1114.         if (PM_GoodPosition ())
  1115.             return;
  1116.     }
  1117.  
  1118.     // go back to the last position
  1119.     VectorCopy (pml.previous_origin, pm->s.origin);
  1120. //    Com_DPrintf ("using previous_origin\n");
  1121. }
  1122.  
  1123. #if 0
  1124. //NO LONGER USED
  1125. /*
  1126. ================
  1127. PM_InitialSnapPosition
  1128.  
  1129. ================
  1130. */
  1131. void PM_InitialSnapPosition (void)
  1132. {
  1133.     int        x, y, z;
  1134.     short    base[3];
  1135.  
  1136.     VectorCopy (pm->s.origin, base);
  1137.  
  1138.     for (z=1 ; z>=-1 ; z--)
  1139.     {
  1140.         pm->s.origin[2] = base[2] + z;
  1141.         for (y=1 ; y>=-1 ; y--)
  1142.         {
  1143.             pm->s.origin[1] = base[1] + y;
  1144.             for (x=1 ; x>=-1 ; x--)
  1145.             {
  1146.                 pm->s.origin[0] = base[0] + x;
  1147.                 if (PM_GoodPosition ())
  1148.                 {
  1149.                     pml.origin[0] = pm->s.origin[0]*0.125;
  1150.                     pml.origin[1] = pm->s.origin[1]*0.125;
  1151.                     pml.origin[2] = pm->s.origin[2]*0.125;
  1152.                     VectorCopy (pm->s.origin, pml.previous_origin);
  1153.                     return;
  1154.                 }
  1155.             }
  1156.         }
  1157.     }
  1158.  
  1159.     Com_DPrintf ("Bad InitialSnapPosition\n");
  1160. }
  1161. #else
  1162. /*
  1163. ================
  1164. PM_InitialSnapPosition
  1165.  
  1166. ================
  1167. */
  1168. void PM_InitialSnapPosition(void)
  1169. {
  1170.     int        x, y, z;
  1171.     short      base[3];
  1172.     static int offset[3] = { 0, -1, 1 };
  1173.  
  1174.     VectorCopy (pm->s.origin, base);
  1175.  
  1176.     for ( z = 0; z < 3; z++ ) {
  1177.         pm->s.origin[2] = base[2] + offset[ z ];
  1178.         for ( y = 0; y < 3; y++ ) {
  1179.             pm->s.origin[1] = base[1] + offset[ y ];
  1180.             for ( x = 0; x < 3; x++ ) {
  1181.                 pm->s.origin[0] = base[0] + offset[ x ];
  1182.                 if (PM_GoodPosition ()) {
  1183.                     pml.origin[0] = pm->s.origin[0]*0.125;
  1184.                     pml.origin[1] = pm->s.origin[1]*0.125;
  1185.                     pml.origin[2] = pm->s.origin[2]*0.125;
  1186.                     VectorCopy (pm->s.origin, pml.previous_origin);
  1187.                     return;
  1188.                 }
  1189.             }
  1190.         }
  1191.     }
  1192.  
  1193.     Com_DPrintf ("Bad InitialSnapPosition\n");
  1194. }
  1195.  
  1196. #endif
  1197.  
  1198. /*
  1199. ================
  1200. PM_ClampAngles
  1201.  
  1202. ================
  1203. */
  1204. void PM_ClampAngles (void)
  1205. {
  1206.     short    temp;
  1207.     int        i;
  1208.  
  1209.     if (pm->s.pm_flags & PMF_TIME_TELEPORT)
  1210.     {
  1211.         pm->viewangles[YAW] = SHORT2ANGLE(pm->cmd.angles[YAW] + pm->s.delta_angles[YAW]);
  1212.         pm->viewangles[PITCH] = 0;
  1213.         pm->viewangles[ROLL] = 0;
  1214.     }
  1215.     else
  1216.     {
  1217.         // circularly clamp the angles with deltas
  1218.         for (i=0 ; i<3 ; i++)
  1219.         {
  1220.             temp = pm->cmd.angles[i] + pm->s.delta_angles[i];
  1221.             pm->viewangles[i] = SHORT2ANGLE(temp);
  1222.         }
  1223.  
  1224.         // don't let the player look up or down more than 90 degrees
  1225.         if (pm->viewangles[PITCH] > 89 && pm->viewangles[PITCH] < 180)
  1226.             pm->viewangles[PITCH] = 89;
  1227.         else if (pm->viewangles[PITCH] < 271 && pm->viewangles[PITCH] >= 180)
  1228.             pm->viewangles[PITCH] = 271;
  1229.     }
  1230.     AngleVectors (pm->viewangles, pml.forward, pml.right, pml.up);
  1231. }
  1232.  
  1233. /*
  1234. ================
  1235. Pmove
  1236.  
  1237. Can be called by either the server or the client
  1238. ================
  1239. */
  1240. void Pmove (pmove_t *pmove)
  1241. {
  1242.     pm = pmove;
  1243.  
  1244.     // clear results
  1245.     pm->numtouch = 0;
  1246.     VectorClear (pm->viewangles);
  1247.     pm->viewheight = 0;
  1248.     pm->groundentity = 0;
  1249.     pm->watertype = 0;
  1250.     pm->waterlevel = 0;
  1251.  
  1252.     // clear all pmove local vars
  1253.     memset (&pml, 0, sizeof(pml));
  1254.  
  1255.     // convert origin and velocity to float values
  1256.     pml.origin[0] = pm->s.origin[0]*0.125;
  1257.     pml.origin[1] = pm->s.origin[1]*0.125;
  1258.     pml.origin[2] = pm->s.origin[2]*0.125;
  1259.  
  1260.     pml.velocity[0] = pm->s.velocity[0]*0.125;
  1261.     pml.velocity[1] = pm->s.velocity[1]*0.125;
  1262.     pml.velocity[2] = pm->s.velocity[2]*0.125;
  1263.  
  1264.     // save old org in case we get stuck
  1265.     VectorCopy (pm->s.origin, pml.previous_origin);
  1266.  
  1267.     pml.frametime = pm->cmd.msec * 0.001;
  1268.  
  1269.     PM_ClampAngles ();
  1270.  
  1271.     if (pm->s.pm_type == PM_SPECTATOR)
  1272.     {
  1273.         PM_FlyMove (false);
  1274.         PM_SnapPosition ();
  1275.         return;
  1276.     }
  1277.  
  1278.     if (pm->s.pm_type >= PM_DEAD)
  1279.     {
  1280.         pm->cmd.forwardmove = 0;
  1281.         pm->cmd.sidemove = 0;
  1282.         pm->cmd.upmove = 0;
  1283.     }
  1284.  
  1285.     if (pm->s.pm_type == PM_FREEZE)
  1286.         return;        // no movement at all
  1287.  
  1288.     // set mins, maxs, and viewheight
  1289.     PM_CheckDuck ();
  1290.  
  1291.     if (pm->snapinitial)
  1292.         PM_InitialSnapPosition ();
  1293.  
  1294.     // set groundentity, watertype, and waterlevel
  1295.     PM_CatagorizePosition ();
  1296.  
  1297.     if (pm->s.pm_type == PM_DEAD)
  1298.         PM_DeadMove ();
  1299.  
  1300.     PM_CheckSpecialMovement ();
  1301.  
  1302.     // drop timing counter
  1303.     if (pm->s.pm_time)
  1304.     {
  1305.         int        msec;
  1306.  
  1307.         msec = pm->cmd.msec >> 3;
  1308.         if (!msec)
  1309.             msec = 1;
  1310.         if ( msec >= pm->s.pm_time) 
  1311.         {
  1312.             pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT);
  1313.             pm->s.pm_time = 0;
  1314.         }
  1315.         else
  1316.             pm->s.pm_time -= msec;
  1317.     }
  1318.  
  1319.     if (pm->s.pm_flags & PMF_TIME_TELEPORT)
  1320.     {    // teleport pause stays exactly in place
  1321.     }
  1322.     else if (pm->s.pm_flags & PMF_TIME_WATERJUMP)
  1323.     {    // waterjump has no control, but falls
  1324.         pml.velocity[2] -= pm->s.gravity * pml.frametime;
  1325.         if (pml.velocity[2] < 0)
  1326.         {    // cancel as soon as we are falling down again
  1327.             pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT);
  1328.             pm->s.pm_time = 0;
  1329.         }
  1330.  
  1331.         PM_StepSlideMove ();
  1332.     }
  1333.     else
  1334.     {
  1335.         PM_CheckJump ();
  1336.  
  1337.         PM_Friction ();
  1338.  
  1339.         if (pm->waterlevel >= 2)
  1340.             PM_WaterMove ();
  1341.         else {
  1342.             vec3_t    angles;
  1343.  
  1344.             VectorCopy(pm->viewangles, angles);
  1345.             if (angles[PITCH] > 180)
  1346.                 angles[PITCH] = angles[PITCH] - 360;
  1347.             angles[PITCH] /= 3;
  1348.  
  1349.             AngleVectors (angles, pml.forward, pml.right, pml.up);
  1350.  
  1351.             PM_AirMove ();
  1352.         }
  1353.     }
  1354.  
  1355.     // set groundentity, watertype, and waterlevel for final spot
  1356.     PM_CatagorizePosition ();
  1357.  
  1358.     PM_SnapPosition ();
  1359. }
  1360.  
  1361.